from fastapi import APIRouter
from fastapi import FastAPI, Cookie,Header, Path, Query
from enum import Enum
from typing import Optional, List
from pydantic import BaseModel, Field
from datetime import date


module01 = APIRouter()


@module01.get('params', tags=["message"])
def params():
    return {"message": "this is a sample message"}


# 定义枚举类型
class ModelName(str, Enum):
    alexnet = "alexnet"
    resnet = "resnet"
    lenet = "lenet"


fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]


# 最简单的请求
@module01.get("/")
async def root():
    return {"message": "Hello World"}


# 路径参数
@module01.get("/items/{item_id}")
async def read_item(item_id: int):
    return {"item_id": item_id}


# 路径参数2
@module01.get("/models/{model_name}")
async def get_model(model_name: ModelName):
    if model_name == ModelName.alexnet:
        return {"model_name": model_name, "message": "Deep Learning FTW!"}

    if model_name.value == 'lenet':
        return {"model_name": model_name, "message": "LeCNN all the images"}

    return {"model_name": model_name, "message": "Have some residuals"}


@module01.get("/files/{file_path:path}")
async def read_file(file_path: str):
    return {"file_path": file_path}


# 查询参数
@module01.get("/items/")
async def read_item(skip: int = 0, limit: int = 3):
    return fake_items_db[skip: skip + limit]


@module01.get("/items2/{item_id}")
async def read_item(item_id: str, q: Optional[str] = None):
    if q:
        return {"item_id": item_id, "q": q}
    return {"item_id": item_id}


# 路程参数限定
@module01.get("/test_path/{num}")
async def test_path(
    num: int = Path(..., title="Your number", description="描述信息", ge=1, le=10)

):
    return num


# 多种参数的获取
@module01.get("/users/{user_id}/items/{item_id}")
async def read_user_item(
    user_id: int, item_id: str, q: Optional[str] = None, short: bool = False
):
    # http://localhost:8000/users/8488/items/item01?short=True&q=11
    item = {"item_id": item_id, "owner_id": user_id}
    if q:
        item.update({"q": q})
    if not short:
        item.update(
            {"description": "This is an amazing item that has a long description"}
        )
    return item


@module01.get("/items3/{item_id}")
async def read_user_item(
    item_id: str, needy: str, skip: int = 0, limit: Optional[int] = None
):
    # needy：为必须的查询参数  skip：有默认值的查询参数  limit:为可选参数
    item = {"item_id": item_id, "needy": needy, "skip": skip, "limit": limit}
    return item


class Item(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = None


@module01.post("/items4/")
async def create_item(item: Item):
    return item


class CityInfo(BaseModel):
    name: str = Field(..., description="城市名称")
    country: str
    country_code: str = None
    country_population: int = Field(default=800, title="人口数量", description="国家的人口数量")

    class Config:  # 为类设置子类
        schema_extra = {
            "example": {
                "name": "Shanghai",
                "country": "China",
                "country_code": "CN",
                "country_population": 1400000
            }
        }


# body体的格式为 example里的内容
@module01.post("/request_body/city")
async def request_city(city: CityInfo):
    return city.dict()


# 请求里的多种参数获取
@module01.post("/request_body/city/{city_code}")
def mix_city_info(
    city_code: str,  # = Path(..., title="城市code"),
    city01: CityInfo,
    city02: CityInfo,
    confirmed: int = Query(ge=0, description="确诊树", default=0),
    deaths: int = Query(ge=0, description="死亡数", default=0),
):
    if city_code == "Shanghai":
        return {"city_code": city_code, "detail": {"confirmed": confirmed, "deaths": deaths}}
    return city01.dict(), city02.dict()


class RequestDataNested(BaseModel):
    cityList: List[CityInfo] = None
    date: date
    confirmed: int = Field(ge=0, description="确诊数", default=0)
    death: int = Field(ge=0, description="死亡数", default=0)
    recovered: int = Field(ge=0, description="痊愈数", default=0)


# 嵌套的请求参数
@module01.post('/request_body/nested')
def nested(data: RequestDataNested):
    return data


# cookie
@module01.post("/test_cookie")
async def read_items(ads_id: Optional[str] = Cookie(None)):
    return {"ads_id": ads_id}


@module01.get("/test_header")
async def read_items(user_agent: Optional[str] = Header(None)):
    return {"User-Agent": user_agent}


@module01.get("/test_header2")
async def read_items(
    strange_header: Optional[str] = Header(None, convert_underscores=True)
):
    return {"strange_header": strange_header}


